package nels4561;

import java.util.ArrayList;
import java.util.Set;

import spacewar2.objects.Asteroid;
import spacewar2.objects.Base;
import spacewar2.objects.Beacon;
import spacewar2.objects.Ship;
import spacewar2.objects.SpacewarObject;
import spacewar2.simulator.Toroidal2DPhysics;

public class Cluster {
	//used to define the size of a cluster
	static final double CLUSTER_RADIUS = 5;
	//used to define the value of a cluster compared to regular asteroids
	static final double CLUSTER_WEIGHT = .0001;
	
	/**
	 * Distance from ship to cluster.
	 * The ship is used for consistency purposes so that it can work well with Ego.
	 * */
	double shipToCluster;
	
	/**
	 * Distance from ship to cluster.
	 * The ship is used for consistency purposes so that it can work well with Ego.
	 * */
	double baseToCluster;
	
	/**
	 * Total value in the cluster.
	 * The sum of beacons and mineable asteroids
	 * */
	double clusterValue;
	
	/**
	 * Asteroid at the center of the cluster
	 * */
	Asteroid clusterHub;
	
	/**
	 * Last Beacon found in a cluster
	 * */
	Beacon clusterBeacon;
	
	/**
	 * Last Beacon found in a cluster
	 * */
	Base clusterBase;
	
	/**
	 * Cluster of SpacewarObjects around an Asteroid
	 * */
	ArrayList<SpacewarObject> cluster;
	
	Cluster(Toroidal2DPhysics space, Ship ship, Asteroid asteroid)
	{
		shipToCluster = 0.0;
		baseToCluster = Double.MAX_VALUE;
		clusterValue = 0.0;
		clusterHub = asteroid;
		clusterBeacon = null;
		clusterBase = null;
		cluster = new ArrayList<SpacewarObject>();
		generateCluster(space, ship, clusterHub);
	}
	
	/**
	 * Creates a cluster from an asteroid
	 * 
	 * @param space: spacewar environment
	 * @param ship: current ship
	 * @param asteroid: hub of the cluster
	 * */
	void generateCluster(Toroidal2DPhysics space, Ship ship, Asteroid asteroid) 
			{
		//set the distance to the cluster as the distance from from the cluster hub asteroid to the ship
		shipToCluster = space.findShortestDistance(ship.getPosition(), asteroid.getPosition());
		
		if (asteroid.isMineable()) 
		{
			clusterValue = asteroid.getMoney();
			
			Set<Asteroid> asteroids = space.getAsteroids();
			
			//for each asteroid, add the value of the asteroid to the clusterValue
			for (Asteroid neighborAsteroid : asteroids)
			{
				if (neighborAsteroid.getId() != asteroid.getId() && neighborAsteroid.isMineable()) 
				{
					if (space.findShortestDistance(asteroid.getPosition(),
							neighborAsteroid.getPosition()) < CLUSTER_RADIUS) 
					{
						clusterValue += EgocentricRepresentation.MONEY_WEIGHT*neighborAsteroid.getMoney();
						cluster.add(neighborAsteroid);
					}
				}
			}
			
			Set<Beacon> beacons = space.getBeacons();
			
			//for each beacon in range, add the value of a beacon to the clusterValue
			for (Beacon neighborBeacon : beacons) 
			{
				if (space.findShortestDistance(asteroid.getPosition(),
						neighborBeacon.getPosition()) < CLUSTER_RADIUS) 
				{
					clusterBeacon = neighborBeacon;
					clusterValue += (EgocentricRepresentation.BEACON_VALUE - EgocentricRepresentation.BEACON_WEIGHT*ship.getEnergy());
					cluster.add(neighborBeacon);
				}
			}
			
			Set<Base> bases = space.getBases();
			
			for (Base base : bases)
			{
				double newDistance = space.findShortestDistance(clusterHub.getPosition(), base.getPosition());
				if (newDistance < baseToCluster)
				{
					baseToCluster = newDistance;
					clusterBase = base;
				}
			}
		}
		clusterValue = CLUSTER_WEIGHT*(clusterValue - space.findShortestDistance(clusterHub.getPosition(), clusterBase.getPosition()))/shipToCluster;
	}

}
